from typing import Dict, Optional, Tuple, List
import logging
import time
import random
from enum import Enum, auto
from DrissionPage import ChromiumPage, ChromiumOptions
from DrissionPage.common import Keys, By
from .utils.error_handler import ErrorHandler, UnlockErrorType
from .config import Config
from .package import variables
import functools
import re
import requests
from hashlib import md5
import os

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class UnlockStep(Enum):
    """解锁流程的步骤枚举"""
    INIT = auto()                    # 初始化
    LOAD_DATA = auto()               # 加载数据
    NAVIGATE_PAGE = auto()           # 访问页面
    SELECT_NO_PHONE = auto()         # 选择无手机号
    INPUT_IMEI = auto()              # 输入IMEI
    CONFIRM_CHECKBOX = auto()        # 确认复选框
    NEXT_STEP = auto()               # 下一步
    INPUT_PERSONAL_INFO = auto()     # 输入个人信息
    SUBMIT_REQUEST = auto()          # 提交请求
    CHECK_RESULT = auto()            # 检查结果
    HANDLE_EMAIL = auto()            # 处理邮件
    UPDATE_STATUS = auto()           # 更新状态
    COMPLETE = auto()                # 完成

class UnlockState:
    def __init__(self):
        self.feedback_modal_closed = False  # 跟踪反馈弹窗是否已关闭
        self.current_step = UnlockStep.INIT
        self.car_id_data = None
        self.email = None
        self.error_message = None
        self.success = False
        self.retry_count = 0
        self.max_retries = 3
        self.result_message = None
        self.request_number = None
        self.status = 2  # 默认失败状态


class CoreHandler:
    # 添加状态常量
    STATUS_SUCCESS = 1  # 解锁成功
    STATUS_FAILED = 2   # 解锁失败
    STATUS_CONFIRMED = 3  # 已确认状态
    STATUS_TECH_FAILED = 4  # 技术原因失败
    STATUS_PENDING = 5  # 待处理状态
    STATUS_PROCESSING = 6  # 处理中状态
    STATUS_DENIED = 7  # 解锁被拒绝
    STATUS_UNKNOWN = 8  # 未知状态
    STATUS_APPROVED = 9  # 解锁批准

    def __init__(self, task_id: int = 0):
        """
        初始化处理器
        :param task_id: 任务ID，用于区分不同的任务实例
        """
        self.logger = logging.getLogger(__name__)
        self.browser = None  # 改用browser存储Chromium对象
        self.page = None    # page用于存储当前标签页
        self.error_handler = ErrorHandler()
        self.state = UnlockState()
        self.task_id = task_id

    def load_data(self, imei: str, email: str, first_name: str, last_name: str, phone: str) -> bool:
        """
        加载用户数据
        :param imei: IMEI号码
        :param email: 邮箱地址
        :param first_name: 名字
        :param last_name: 姓氏
        :param phone: 电话号码
        :return: 是否成功
        """
        try:
            # 保存用户数据
            self.state.email = email
            self.state.car_id_data = {
                'imei': imei,
                'first_name': first_name,
                'last_name': last_name,
                'phone': phone
            }
            
            self.logger.info(f"成功加载用户数据: email={email}, imei={imei}")
            return True
            
        except Exception as e:
            self.logger.error(f"加载数据失败: {str(e)}")
            self.state.error_message = str(e)
            return False

    def navigate_page(self) -> bool:
        """导航到解锁页面"""
        try:
            # 验证代理是否生效
            self.logger.info("正在验证代理(ipinfo)...")
            self.page.get("https://ipinfo.io/json")
            time.sleep(2)
            try:
                ip_info = self.page.ele('tag:pre').text
                self.logger.info(f"当前代理IP信息: {ip_info}")
            except Exception as e:
                self.logger.error(f"获取代理IP信息失败: {str(e)}")
                return False
            
            self.logger.info("正在访问AT&T解锁主页...")
            # 尝试正常流程
            self.page.get("https://www.att.com/deviceunlock/")
            time.sleep(10)
            
            # 处理可能的弹窗
            self.handle_popups()
            
            # 等待并点击品牌选择按钮
            self.logger.info("等待品牌选择按钮...")
            brand_button = self.page.ele('xpath://button[contains(@id, "Selection_Menu_Device_Selection")]', timeout=10)
            if not brand_button:
                self.logger.error("未找到品牌选择按钮")
                return False
                
            brand_button.click()
            time.sleep(1)
            
            # 处理可能的弹窗
            self.handle_popups()
            
            # 等待并选择Apple品牌
            self.logger.info("等待Apple选项...")
            apple_option = self.page.ele('xpath://li[@role="option" and contains(., "Apple")]', timeout=10)
            if not apple_option:
                self.logger.error("未找到Apple选项")
                return False
                
            apple_option.click()
            time.sleep(1)
            
            # 处理可能的弹窗
            self.handle_popups()
            
            # 等待并点击"Submit an unlock request"按钮
            self.logger.info("等待提交解锁请求链接...")
            unlock_link = self.page.ele('xpath://a[contains(@href, "/deviceunlock/unlockstep1")]', timeout=10)
            if not unlock_link:
                self.logger.error("未找到提交解锁请求链接")
                # 如果上面的步骤有任何一步失败，直接跳转到解锁步骤页面
                raise Exception("正常流程执行失败，将直接跳转到解锁步骤页面")
                
        except Exception as e:
            self.logger.warning(f"正常流程执行出错: {str(e)}")
            # 尝试直接访问解锁步骤页面
            try:
                self.page.get("https://www.att.com/deviceunlock/unlockstep1")
                time.sleep(5)
                self.handle_popups()
                return True
            except Exception as direct_err:
                self.logger.error(f"直接访问解锁页面失败: {str(direct_err)}")
                return False
                
        try:
            # 点击链接并获取新标签页
            new_tab = unlock_link.click.for_new_tab()
            if not new_tab:
                self.logger.error("新标签页未打开")
                return False
            
            # 更新当前页面对象
            self.page = new_tab
            time.sleep(2)
            
            # 处理可能的弹窗
            self.handle_popups()
            
            return True
            
        except Exception as e:
            self.logger.error(f"导航到解锁页面失败: {str(e)}")
            return False

    def select_no_phone(self) -> bool:
        """选择'没有AT&T手机号码'选项"""
        try:
            self.logger.info("选择'没有AT&T手机号码'选项...")
            
            # 切换到最新的标签页
            self.switch_to_latest_tab()
            
            # 处理可能的弹窗
            self.handle_popups()
            
            self.logger.info("等待并点击No选项")
            # 等待并点击"No"选项
            no_radio = self.page.ele('xpath://input[@type="radio" and @id="customLabelScenario-1"]')
            if not no_radio:
                self.logger.error("未找到'No'选项")
                return False
                
            # 使用动作链点击选项
            ac = self.page.actions
            ac.move_to(no_radio)
            ac.click()
            time.sleep(2)
            
            self.logger.info("成功选择'No'选项")
            return True
        
        except Exception as e:
            self.logger.error(f"选择'没有AT&T手机号码'选项失败: {str(e)}")
            return False

    def handle_popups(self) -> bool:
        """处理页面中的弹窗"""
        try:
            # 等待页面加载完成
            time.sleep(3)
            
            # 处理常见的反馈弹窗
            self.check_feedback_modal()
            
            # 处理 cookie 同意弹窗
            cookie_button = self.page.ele('css:#consent_prompt_submit')
            if cookie_button:
                self.logger.info("发现cookie同意弹窗，点击接受")
                cookie_button.click()
                time.sleep(1)
            
            # 处理"No"选项按钮，通常出现在某些弹窗中
            no_button = self.page.ele('xpath://button[contains(text(), "No")]')
            if no_button:
                self.logger.info("发现'No'按钮弹窗，点击'No'")
                no_button.click()
                time.sleep(1)
            
            # 通用关闭按钮
            close_button = self.page.ele('css:.close-button, .close, .modal-close')
            if close_button:
                self.logger.info("发现关闭按钮，点击关闭")
                close_button.click()
                time.sleep(1)
            
            # 检查是否有其他需要处理的弹窗...
            # 可以根据实际情况添加更多处理逻辑
            
            return True
            
        except Exception as e:
            self.logger.error(f"处理弹窗失败: {str(e)}")
            return False

    def input_imei(self, imei: str) -> bool:
        """输入IMEI号码"""
        try:
            self.logger.info(f"正在输入IMEI: {imei}")
            # 切换到最新的标签页
            self.switch_to_latest_tab()
            # 处理可能的弹窗
            self.handle_popups()

            # 获取输入框元素
            imei_input = self.page.ele('xpath://input[@type="text" and contains(@id, "imei")]')
            if not imei_input:
                self.logger.error("未找到IMEI输入框")
                self.set_error_state()
                return False
            
            
            # 创建动作链并移动到输入框
            ac = self.page.actions
            ac.move_to(imei_input)
            ac.click()
            time.sleep(random.uniform(0.5, 1))
            
            # 处理可能的弹窗
            self.handle_popups()

            # 清空输入框
            imei_input.clear()
            time.sleep(random.uniform(0.3, 0.7))
            
            # 模拟人工输入，一个数字一个数字地输入
            for digit in imei:
                ac.type(digit)
                time.sleep(random.uniform(0.1, 0.3))
            
            # 等待验证完成
            time.sleep(random.uniform(4, 6))
            
            has_error, _ = self.check_error_message()
            if has_error:
                return False
            
            # 使用完全匹配的选择器检查设备信息
            device_info = self.page.ele('css:.pad-t-md.pad-l-none.grid-col-8.flex')
            if device_info:
                make = self.page.ele('css:.grid-col-4.pad-t-md.pad-l-none .type-base.rte-styles')
                model = self.page.ele('css:.grid-col-10.pad-t-md.pad-l-none .type-base.rte-styles')
                
                if make and model:
                    self.logger.info(f"成功验证IMEI，设备信息 - 品牌: {make.text.strip()}, 型号: {model.text.strip()}")
            return True
            
            self.logger.warning("未检测到设备信息，IMEI可能无效")
            self.set_error_state()
            return False
            
        except Exception as e:
            self.logger.error(f"输入IMEI失败: {str(e)}")
            self.set_error_state()
            return False

    def confirm_checkbox(self) -> bool:
        """确认复选框"""
        try:
            self.logger.info("正在确认复选框...")
            # 处理可能的弹窗
            self.handle_popups()

            # 等待并定位复选框
            checkbox = self.page.ele('xpath://input[@type="checkbox"]')
            if not checkbox:
                self.logger.error("未找到同意协议复选框")
                return False
            
            # 使用动作链点击复选框
            ac = self.page.actions
            ac.move_to(checkbox)
            ac.click()
            time.sleep(1)
            
            # 直接返回True，因为我们已经成功点击了复选框
            self.logger.info("成功勾选同意协议")
            return True
            
        except Exception as e:
            self.logger.error(f"确认复选框失败: {str(e)}")
            return False

    def next_step(self) -> bool:
        """进入下一步"""
        try:
            self.logger.info("正在进入下一步...")
            # 处理可能的弹窗
            self.handle_popups()

            # 等待并点击下一步按钮
            next_button = self.page.ele('css:.btn-primary .width-xxxl')
            if not next_button:
                self.logger.error("未找到Next按钮")
                return False
                
            # 使用动作链点击按钮
            ac = self.page.actions
            ac.move_to(next_button)
            ac.click()
            time.sleep(2)
            
            has_error, _ = self.check_error_message()
            if has_error:
                return False
            
            return True
            
        except Exception as e:
            self.logger.error(f"进入下一步失败: {str(e)}")
            return False

    def input_personal_info(self, email: str, first_name: str, last_name: str, phone: str) -> bool:
        """
        输入个人信息
        :param email: 邮箱地址
        :param first_name: 名字
        :param last_name: 姓氏
        :param phone: 电话号码
        :return: 是否成功
        """
        try:
            self.logger.info("正在输入个人信息...")
            # 切换到最新的标签页
            self.switch_to_latest_tab()
            # 处理可能的弹窗
            self.handle_popups()

            ac = self.page.actions
            
            # 输入First name
            first_name_input = self.page.ele('#non_att_first_name')
            if not first_name_input:
                self.logger.error("未找到First name输入框")
                return False
            ac.move_to(first_name_input)
            ac.click()
            time.sleep(random.uniform(0.5, 1))
            # 模拟人工输入First name
            for char in first_name:
                ac.type(char)
                time.sleep(random.uniform(0.1, 0.3))
            time.sleep(random.uniform(0.3, 0.7))

            # 处理可能的弹窗
            self.handle_popups()

            # 输入Last name
            last_name_input = self.page.ele('#non_att_last_Name')
            if not last_name_input:
                self.logger.error("未找到Last name输入框")
                return False
            ac.move_to(last_name_input)
            ac.click()
            time.sleep(random.uniform(0.5, 1))
            # 模拟人工输入Last name
            for char in last_name:
                ac.type(char)
                time.sleep(random.uniform(0.1, 0.3))
            time.sleep(random.uniform(0.3, 0.7))
            
            # 处理可能的弹窗
            self.handle_popups()

            # 输入Mobile number
            mobile = self.page.ele('#non_att_wirelessNo')
            if not mobile:
                self.logger.error("未找到Mobile number输入框")
                return False
            ac.move_to(mobile)
            ac.click()
            time.sleep(random.uniform(0.5, 1))
            # 模拟人工输入电话号码
            for digit in phone:
                ac.type(digit)
                time.sleep(random.uniform(0.1, 0.3))
            time.sleep(random.uniform(0.3, 0.7))
            
            # 处理可能的弹窗
            self.handle_popups()

            # 输入Email
            email_input = self.page.ele('#non_att_emailAddr')
            if not email_input:
                self.logger.error("未找到Email输入框")
                return False
            ac.move_to(email_input)
            ac.click()
            time.sleep(random.uniform(0.5, 1))
            # 模拟人工输入邮箱
            for char in email:
                ac.type(char)
                time.sleep(random.uniform(0.1, 0.3))
            time.sleep(random.uniform(0.3, 0.7))
            
            # 处理可能的弹窗
            self.handle_popups()

            # 输入Confirm email
            confirm_email = self.page.ele('#confirmEmailAddr')
            if not confirm_email:
                self.logger.error("未找到Confirm email输入框")
                return False
            ac.move_to(confirm_email)
            ac.click()
            time.sleep(random.uniform(0.5, 1))
            # 模拟人工输入确认邮箱
            for char in email:
                ac.type(char)
                time.sleep(random.uniform(0.1, 0.3))
            time.sleep(random.uniform(0.3, 0.7))
            
            return True
            
        except Exception as e:
            self.logger.error(f"输入个人信息失败: {str(e)}")
            return False

    def submit_request(self) -> bool:
        """提交解锁请求"""
        try:
            self.logger.info("正在提交解锁请求...")
            
            # 等待并点击提交按钮
            submit_button = self.page.ele('css:.btn-primary .width-xxxl')
            if not submit_button:
                self.logger.error("未找到Submit按钮")
                return False
            
            # 使用动作链点击按钮
            ac = self.page.actions
            ac.move_to(submit_button)
            ac.click()
            time.sleep(3)
            
            has_error, _ = self.check_error_message()
            if has_error:
                return False
            
            return True
            
        except Exception as e:
            self.logger.error(f"提交解锁请求失败: {str(e)}")
            self.state.error_message = str(e)
            return False

    def check_result(self) -> bool:
        """检查解锁结果"""
        try:
            self.logger.info("正在检查解锁结果...")
            
            # 等待结果页面加载
            time.sleep(3)
            # 切换到最新的标签页
            self.switch_to_latest_tab()
            # 检查是否在感谢页面
            thanks_header = self.page.ele('css:.thankYouBodyHeader')
            if not thanks_header:
                self.logger.error("未找到感谢页面标题")
                return False
            
            # 获取请求编号
            request_number_elem = self.page.ele('css:.type-base.rte-styles span.css-bold')
            if request_number_elem:
                request_number = request_number_elem.text
                self.logger.info(f"获取到请求编号: {request_number}")
                self.state.request_number = request_number
            else:
                self.logger.error("未找到请求编号")
                return False
            
            # 处理邮件确认
            return self.handle_email_confirmation()
            
        except Exception as e:
            self.logger.error(f"检查解锁结果失败: {str(e)}")
            return False

    def handle_email_confirmation(self) -> bool:
        """处理邮件确认流程"""
        try:
            self.logger.info("开始处理邮件确认...")
            from datetime import datetime
            
            # 获取当前时间
            now_datetime = datetime.now().strftime('%Y-%m-%d %H:%M')
            
            # 循环获取确认链接
            max_retries = 10
            retry_count = 0
            confirm_link = None
            
            while retry_count < max_retries:
                self.logger.info(f"第 {retry_count + 1} 次尝试获取确认链接...")
                confirm_link = self.get_confirm_link(self.state.email, now_datetime)
                if confirm_link:
                    break
                    
                retry_count += 1
                time.sleep(5)
            
            if not confirm_link:
                self.logger.error("未能获取确认链接")
                return False
            
            # 点击确认链接
            if not self.click_confirm_link(confirm_link):
                self.logger.error("点击确认链接失败")
                return False
            
            # 如果已经获取到请求编号，查询解锁状态
            if self.state.request_number:
                self.logger.info(f"已获取请求编号: {self.state.request_number}，尝试查询状态...")
                # 等待一段时间再查询，因为请求需要处理时间
                time.sleep(10)
                # 查询解锁状态
                self.query_unlock_status(self.state.request_number, imei=self.state.car_id_data['imei'], max_attempts=5)
                
                # 如果查询结果是"处理中"，则之后会在run方法中再次查询
                if self.state.result_message and "处理中" not in self.state.result_message:
                    self.logger.info(f"已获取最终解锁状态: {self.state.result_message}")
                    return True
            
            # 等待并获取解锁结果
            retry_count = 0
            result = None
            
            while retry_count < max_retries:
                self.logger.info(f"第 {retry_count + 1} 次尝试获取解锁结果...")
                result = self.parse_result_email(self.state.email, now_datetime)
                if result and result != "未找到结果邮件" and result != "解析失败":
                    self.logger.info(f"获取到解锁结果: {result}")
                    self.state.result_message = result
                    break
                    
                retry_count += 1
                time.sleep(10)
            
            if not result or result in ["未找到结果邮件", "解析失败"]:
                self.logger.error("未能通过邮件获取解锁结果")
                # 如果已经通过状态查询获取了结果，则依然返回成功
                if self.state.result_message and self.state.result_message != "In Progress (处理中)":
                    return True
                return False
            
            return True
            
        except Exception as e:
            self.logger.error(f"处理邮件确认失败: {str(e)}")
            return False

    def get_confirm_link(self, email: str, now_datetime: str) -> str:
        """获取确认链接"""
        try:
            # 设置API参数
            url = "https://api.rurl.vip/mail/get"
            params = {
                "user": "318258885",
                "token": "342b29f569914a77dbdc2923b5dbacb1cd12eeb1",
                "receiver": email,
                "subject": "Heads up! You have 24 hours to confirm your unlock request.",
                "type": "HTML",
                "sender": "att-online.services@account.att-mail.com",
                "time": now_datetime
            }
            
            # 正则表达式匹配链接
            link_pattern = re.compile(
                "Make sure you \n(?P<url>.*?)\nconfirm your request  within 24 hours or we'll have to cancel it.\n",
                re.DOTALL
            )
            
            # 尝试获取邮件内容
            response = requests.get(url, params=params)
            self.logger.info(f"邮件API响应: {response.text}")
            
            # 提取链接
            match = link_pattern.search(response.text)
            if match:
                confirm_link = match.group('url').strip()
                self.logger.info(f"成功获取确认链接: {confirm_link}")
                return confirm_link
            else:
                self.logger.warning("未找到确认链接")
                return ""
                
        except Exception as e:
            self.logger.error(f"获取确认链接失败: {str(e)}")
            return ""

    def click_confirm_link(self, confirm_link: str) -> bool:
        """点击确认链接"""
        try:
            self.logger.info(f"正在访问确认链接: {confirm_link}")
            
            # 使用当前页面对象访问链接
            self.page.get(confirm_link)
            time.sleep(5)  # 等待页面加载
            
            # 切换到最新的标签页
            self.switch_to_latest_tab()
            
            # 检查是否在确认成功页面
            if "emailconfirmationsuccess" in self.page.url:
                # 获取请求编号
                request_number_elem = self.page.ele('css:.type-base.rte-styles span.css-bold')
                if request_number_elem and "NUL" in request_number_elem.text:
                    request_number = request_number_elem.text.strip()
                    # 提取NUL开头的编号
                    match = re.search(r'NUL\d+', request_number)
                    if match:
                        self.state.request_number = match.group(0)
                        self.logger.info(f"确认成功，请求编号: {self.state.request_number}")
                        
                        # 调用后台接口更新请求编号
                        if self.update_request_number_to_backend():
                            self.logger.info("成功将请求编号更新到后台")
                        else:
                            self.logger.error("更新请求编号到后台失败")
                        
                        # 成功后立即查询解锁状态
                        if self.state.request_number:
                            self.state.status = self.STATUS_CONFIRMED
                            # 初次查询状态
                            self.query_unlock_status(self.state.request_number, imei=self.state.car_id_data['imei'], max_attempts=5)
                            return True
                self.state.status = self.STATUS_CONFIRMED
                return True
            
            # 检查是否在错误页面
            if "error" in self.page.url:
                error_text = self.page.ele('css:.type-base.rte-styles')
                if error_text:
                    error_text_str = error_text.text.strip()
                    self.state.error_message = error_text_str
                    # 检查是否是技术错误
                    if "we're having technical issues" in error_text_str:
                        self.state.status = self.STATUS_TECH_FAILED
                        self.logger.error(f"确认失败，技术错误: {error_text_str}")
                    else:
                        self.state.status = self.STATUS_FAILED
                        self.logger.error(f"确认失败，错误信息: {error_text_str}")
                else:
                    self.state.error_message = "确认链接访问失败，未知错误"
                    self.state.status = self.STATUS_FAILED
                return False
            
            # 如果既不是成功页面也不是错误页面，记录错误
            self.state.error_message = "确认链接访问失败，未知页面"
            self.state.status = self.STATUS_FAILED
            return False
            
        except Exception as e:
            self.logger.error(f"点击确认链接失败: {str(e)}")
            self.state.error_message = str(e)
            self.state.status = self.STATUS_FAILED
            return False
            
    def update_request_number_to_backend(self) -> bool:
        """向后台更新请求编号"""
        try:
            if not self.state.request_number:
                self.logger.error("无法更新请求编号: 请求编号为空")
                return False
                
            # 构建请求URL
            base_url = "http://localhost:8001"
            url = f"{base_url}/unlock/request/update/{self.task_id}"
            
            # 构建请求数据
            data = {
                "request_number": self.state.request_number
            }
            
            # 发送POST请求
            self.logger.info(f"向后台更新请求编号: {url}, 数据: {data}")
            response = requests.post(url, json=data)
            
            # 检查响应
            if response.status_code in [200, 201]:
                self.logger.info(f"请求编号更新成功: {response.text}")
                return True
            else:
                self.logger.error(f"请求编号更新失败，状态码: {response.status_code}, 响应: {response.text}")
                return False
                
        except Exception as e:
            self.logger.error(f"更新请求编号到后台失败: {str(e)}")
            return False

    def query_unlock_status(self, request_number: str, imei: str = None, max_attempts: int = 1) -> bool:
        """查询解锁状态"""
        try:
            # 如果没有请求编号，则无法查询
            if not request_number:
                self.logger.error("无法查询状态：没有请求编号")
                return False

            # 从状态页开始
            self.navigate_status_page()
            
            # 输入请求信息并点击查询
            self.fill_status_form(request_number, imei)
            
            # 提交表单
            submit_button = self.page.ele('xpath://button[@type="submit"]')
            if not submit_button:
                self.logger.error("无法找到提交按钮")
                return False
            
            self.logger.info("点击提交按钮查询状态")
            submit_button.click()
            time.sleep(5)  # 等待页面加载
            
            # 解析结果页面
            return self.parse_result_page()
            
        except Exception as e:
            self.logger.error(f"查询解锁状态失败: {str(e)}")
            self.state.error_message = str(e)
            return False
            
    def parse_result_page(self) -> bool:
        """解析结果页面"""
        try:
            self.logger.info("解析结果页面...")
            
            # 等待加载完成
            time.sleep(5)
            
            # 获取状态文本
            status_element = self.page.ele('css:.deviceunlock-status-text')
            if not status_element:
                self.logger.error("未找到状态文本元素")
                self.state.status = self.STATUS_UNKNOWN
                print(f"STATUS:{self.STATUS_UNKNOWN} 未找到状态文本")
                return False
            
            # 获取状态文本
            status_text = status_element.text
            
            if not status_text:
                self.logger.error("状态文本为空")
                self.state.status = self.STATUS_UNKNOWN
                print(f"STATUS:{self.STATUS_UNKNOWN} 状态文本为空")
                return False
            
            self.logger.info(f"状态文本: {status_text}")
            
            # 解释状态
            if "approved" in status_text.lower():
                self.state.status = self.STATUS_APPROVED
                self.state.success = True
                self.state.result_message = "Unlock Approved"
                self.logger.info("解锁已批准")
                print(f"STATUS:{self.STATUS_APPROVED} 解锁已批准")
                return True
                
            elif "unlocked" in status_text.lower():
                self.state.status = self.STATUS_SUCCESS
                self.state.success = True
                self.state.result_message = "Device Unlocked"
                self.logger.info("设备已解锁")
                print(f"STATUS:{self.STATUS_SUCCESS} 设备已解锁")
                return True
                
            elif "denied" in status_text.lower():
                self.state.status = self.STATUS_DENIED
                self.state.success = False
                self.state.result_message = self.translate_result(status_text)
                self.logger.error(f"解锁被拒绝: {self.state.result_message}")
                print(f"STATUS:{self.STATUS_DENIED} {self.state.result_message}")
                return True
                
            else:
                # 检查是否是其他已知失败情况
                result_message = self.translate_result(status_text)
                self.state.status = self.STATUS_FAILED
                self.state.success = False
                self.state.result_message = result_message
                self.logger.error(f"解锁失败: {result_message}")
                print(f"STATUS:{self.STATUS_FAILED} {result_message}")
                return True
                
        except Exception as e:
            self.logger.error(f"解析结果页面失败: {str(e)}")
            self.state.status = self.STATUS_UNKNOWN
            print(f"STATUS:{self.STATUS_UNKNOWN} 解析结果页面异常: {str(e)}")
            return False

    def translate_result(self, text: str) -> str:
        """翻译并解释解锁结果"""
        try:
            # 常见拒绝原因的映射
            reason_map = {
                "unlock this device too many times": "解锁失败，提交解锁请求过多，已被ATT官方限制30天",
                "past due balance": "解锁失败，此设备处于逾期状态",
                "former owner removes it": "解锁失败，此设备活跃在其他账户中",
                "before 60 days after": "解锁失败，设备活跃未满60天或者激活未满60天",
                "We're missing some info": "解锁失败，此设备处于不活跃状态",
                "lost or stolen": "解锁失败，此设备在ATT官方处于黑名单状态",
                "technical difficulties": "解锁失败，技术原因，请稍后重试"
            }
            
            # 尝试匹配已知原因
            for key, value in reason_map.items():
                if key.lower() in text.lower():
                    return value
                    
            # 如果没有匹配到已知原因，尝试翻译
            return self.translate_text(text)
            
        except Exception as e:
            self.logger.error(f"翻译结果失败: {str(e)}")
            return text

    def parse_result_email(self, email: str, now_datetime: str) -> str:
        """解析解锁结果邮件"""
        try:
            # 尝试获取三种可能的邮件
            subjects = [
                "Heads up! We approved your unlock request.",
                "Heads up! We can't process your unlock request.",
                "Heads up! We can't approve your unlock request."
            ]
            
            for subject in subjects:
                params = {
                    "user": "318258885",
                    "token": "342b29f569914a77dbdc2923b5dbacb1cd12eeb1",
                    "receiver": email,
                    "subject": subject,
                    "type": "html",
                    "time": now_datetime,
                    "sender": "att-online.services@account.att-mail.com"
                }
                
                response = requests.get("https://api.rurl.vip/mail/get", params=params)
                content = response.text
                self.logger.info(f"邮件内容: {content}")
                
                # 解析结果
                if "Let's get your device unlocked" in content:
                    return "Unlocked (已解锁)"
                elif "You've tried to unlock this device too many times" in content:
                    return "解锁失败，提交解锁请求过多，已被ATT官方限制30天"
                elif "You have a past due balance on your account" in content:
                    return "解锁失败，此设备处于逾期状态"
                elif "We can't unlock this device until the former owner removes it" in content:
                    return "解锁失败，此设备活跃在其他账户中"
                elif "在购买后60天之前，我们无法解锁您的设备" in content:
                    return "解锁失败，设备活跃未满60天或者激活未满60天"
                elif "We're missing some info" in content or "我们缺少一些信息" in content:
                    return "解锁失败，此设备处于不活跃状态"
                elif "设备丢失或被盗" in content:
                    return "解锁失败，此设备在ATT官方处于黑名单状态"
                
                # 如果没有匹配到已知结果，尝试提取和翻译
                pattern = re.compile("""<pre>(?P<zhuti>.*?)Hi Cher""", re.DOTALL)
                match = pattern.search(content)
                if match:
                    text = match.group('zhuti').strip().split('\n')[1]
                    return self.translate_text(text)
                    
            return "未找到结果邮件"
            
        except Exception as e:
            self.logger.error(f"解析结果邮件失败: {str(e)}")
            return "解析失败"

    def translate_text(self, text: str) -> str:
        """使用有道翻译API翻译文本"""
        try:
            headers = {
                'Cookie': 'OUTFOX_SEARCH_USER_ID=-690213934@10.108.162.139; OUTFOX_SEARCH_USER_ID_NCOO=1273672853.5782404',
                'Host': 'fanyi.youdao.com',
                'Origin': 'https://fanyi.youdao.com',
                'Referer': 'https://fanyi.youdao.com/',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
            }
            
            # 生成签名
            lts = str(int(time.time() * 100))
            salt = lts + str(random.randint(0, 9))
            sign_data = 'fanyideskweb' + text + salt + 'Ygy_4c=r#e#4EX^NUGUc5'
            sign = md5(sign_data.encode()).hexdigest()
            
            data = {
                'i': text,
                'from': 'AUTO',
                'to': 'AUTO',
                'smartresult': 'dict',
                'client': 'fanyideskweb',
                'salt': salt,
                'sign': sign,
                'lts': lts,
                'bv': 'f0819a82107e6150005e75ef5fddcc3b',
                'doctype': 'json',
                'version': '2.1',
                'keyfrom': 'fanyi.web',
                'action': 'FY_BY_REALTlME',
            }
            
            url = 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
            response = requests.post(url, headers=headers, data=data)
            result = response.json()["translateResult"][0][0]["tgt"]
            self.logger.info(f"翻译结果: {result}")
            return result
            
        except Exception as e:
            self.logger.error(f"翻译失败: {str(e)}")
            return text

    def setup(self) -> bool:
        """初始化浏览器设置"""
        try:
            # 获取当前任务的代理管理器
            proxy_manager = getattr(variables, f'proxy_manager_{self.task_id}', None)
            if not proxy_manager:
                self.logger.error(f"任务 {self.task_id}: 未找到代理管理器")
                return False
            
            # 配置ChromiumOptions
            co = ChromiumOptions()
            
            # 设置浏览器路径 - 使用系统Chrome而不是Chromium
            co.set_paths(browser_path=r'C:\Program Files\Google\Chrome\Application\chrome.exe')
            
            # 使用全新的浏览器环境
            co.new_env(True)
            
            # 添加反检测配置
            co.set_argument('--disable-blink-features=AutomationControlled')
            co.set_argument('--disable-infobars')
            co.set_argument('--disable-popup-blocking')
            co.set_argument('--disable-notifications')
            co.set_argument('--disable-save-password-bubble')
            co.set_argument('--disable-translate')
            co.set_argument('--disable-blink-features')
            co.set_argument('--disable-extensions')
            
            # 模拟正常浏览器特征
            co.set_argument('--window-size=1920,1080')
            co.set_argument('--start-maximized')
            co.set_argument('--enable-javascript')
            co.set_argument('--enable-cookies')
            
            # 设置 User-Agent
            co.set_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36')
            
            # 设置代理和浏览器选项
            proxy_manager.setup_chrome_options(co)
            
            # 设置独立的端口
            co.set_paths(local_port=9322 + self.task_id)
            
            # 创建浏览器对象
            self.browser = ChromiumPage(co)
            self.page = self.browser  # ChromiumPage对象本身就是一个页面对象
            
            # 执行额外的反检测JavaScript
            stealth_js = """
            Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined
            });
            """
            self.page.run_js(stealth_js)
            
            self.logger.info(f"任务 {self.task_id}: 浏览器初始化成功")
            
            # 设置重试次数
            self.browser.set.retry_times(3)  # 设置重试次数为3次
            self.browser.set.retry_interval(1)  # 设置重试间隔为1秒
            
            return True
            
        except Exception as e:
            self.logger.error(f"任务 {self.task_id}: 初始化失败: {str(e)}")
            return False

    def cleanup(self) -> None:
        """
        清理资源，关闭浏览器
        """
        try:
            if self.page:
                try:
                    # 获取错误信息
                    if not self.state.success:
                        self.check_error_message()
                        self.logger.error(f"任务失败: {self.state.error_message}")
                except Exception as e:
                    self.logger.warning(f"获取错误信息时出错: {str(e)}")
                
            # 关闭浏览器
            if self.browser:
                try:
                    self.browser.quit()
                except Exception as e:
                    self.logger.warning(f"关闭浏览器时出错: {str(e)}")
                finally:
                    self.browser = None
                    self.page = None
                    
        except Exception as e:
            self.logger.error(f"清理资源失败: {str(e)}")

    def close(self):
        """关闭浏览器并清理资源"""
        self.cleanup()

    def set_error_state(self):
        """设置错误状态，用于标记是否需要等待用户操作"""
        self.has_error = True 

    def check_feedback_modal(self) -> None:
        """检查并关闭反馈弹窗，如果已经关闭过则跳过"""
        if self.state.feedback_modal_closed:
            return
            
        try:
            # 检查反馈按钮
            feedback_button = self.page.ele(f'css:{Config.FEEDBACK_BUTTON}', timeout=1)
            if feedback_button and feedback_button.states.is_displayed:
                self.logger.info("检测到反馈按钮，尝试关闭...")
                feedback_button.click()
                time.sleep(0.5)
            
            # 检查反馈弹窗
            dialog = self.page.ele(f'css:{Config.FEEDBACK_DIALOG_SELECTOR}', timeout=1)
            if dialog and dialog.states.is_displayed:
                self.logger.info("检测到反馈弹窗，尝试关闭...")
                
                # 尝试点击关闭按钮
                close_button = self.page.ele(f'css:{Config.FEEDBACK_CLOSE_BUTTON}', timeout=1)
                if close_button and close_button.states.is_displayed:
                    close_button.click()
                    time.sleep(0.5)
                    self.state.feedback_modal_closed = True
                    return
                
                # 尝试点击No thanks按钮
                no_thanks = self.page.ele(f'css:{Config.FEEDBACK_NO_THANKS}', timeout=1)
                if no_thanks and no_thanks.states.is_displayed:
                    no_thanks.click()
                    time.sleep(0.5)
                    self.state.feedback_modal_closed = True
                    return
                    
                # 如果都找不到，尝试按Escape键
                self.page.keyboard.press('Escape')
                time.sleep(0.5)
                self.state.feedback_modal_closed = True
            
        except Exception as e:
            self.logger.warning(f"检查反馈弹窗时出错: {str(e)}")
            # 继续执行，不影响主流程

    def check_error_message(self) -> Tuple[bool, bool]:
        """
        检查页面是否有错误信息，如果有则设置到state中
        :return: Tuple[是否存在错误信息, 是否需要继续执行]
        """
        try:
            # 检查所有可能的错误信息容器
            error_selectors = [
                'css:.row.flex-wrap.pad-t-md.pad-t-lg',  # IMEI验证页面的错误
                'css:.flex.flex-items-top.bg-white.rel.pad-sm-lg',  # Submit页面的错误
                'css:[role="status"] .type-base.rte-styles',  # Submit页面的详细错误信息
                'css:.pad-t-lg.pad-l-xs.pad-r-xs .type-base.rte-styles'  # 技术错误信息
            ]
            
            for selector in error_selectors:
                error_div = self.page.ele(selector)
                if error_div and error_div.text:
                    error_text = error_div.text.strip()
                    self.logger.error(f"检测到错误信息: {error_text}")
                    self.state.error_message = error_text
                    
                    # 检查是否是"已在处理中"的错误
                    if "We're already processing an unlock request for this device" in error_text:
                        self.logger.info("检测到设备已有解锁请求在处理中，将继续执行后续步骤...")
                        return True, True  # 有错误，但需要继续执行
                    
                    # 检查是否是技术错误
                    if "we're having technical issues" in error_text:
                        self.logger.error("检测到技术错误，需要稍后重试")
                        self.state.status = self.STATUS_TECH_FAILED
                        return True, False  # 有错误，停止执行
                        
                    return True, False  # 有错误，需要停止执行
                    
            return False, True  # 无错误，继续执行
            
        except Exception as e:
            self.logger.warning(f"检查错误信息时出错: {str(e)}")
            return False, True

    def get_error_message(self) -> str:
        """获取页面上的错误信息"""
        try:
            # 检查常见的错误消息容器
            error_selectors = [
                'css:.error-message',
                'css:.alert-error',
                'css:.validation-error',
                'css:div[role="alert"]',
                'css:.row.flex-wrap.pad-t-md.pad-t-lg',
                'css:.error-text',  # 添加更多可能的错误消息选择器
                'css:.validation-message',
                'xpath://div[contains(@class, "error")]',
                'xpath://div[contains(@class, "alert")]'
            ]
            
            for selector in error_selectors:
                error_elem = self.page.ele(selector, timeout=1)
                if error_elem and error_elem.text.strip():
                    return error_elem.text.strip()
            
            # 如果没有找到错误消息，返回当前步骤
            return f"在步骤 {self.state.current_step.name} 中失败"
            
        except Exception as e:
            self.logger.warning(f"获取错误信息时出错: {str(e)}")
            return f"在步骤 {self.state.current_step.name} 中失败"

    def process_unlock_request(self, imei: str, email: str, first_name: str, last_name: str, phone: str) -> bool:
        """
        处理解锁请求的主流程
        :param imei: IMEI号码
        :param email: 邮箱地址
        :param first_name: 名字
        :param last_name: 姓氏
        :param phone: 电话号码
        :return: 是否成功
        """
        try:
            # 加载数据
            if not self.load_data(imei, email, first_name, last_name, phone):
                return False
                
            # 执行解锁流程的每个步骤
            steps = [
                self.clear_cache,
                self.navigate_page,
                self.select_no_phone,
                lambda: self.input_imei(imei),
                self.confirm_checkbox,
                self.next_step,
                lambda: self.input_personal_info(email, first_name, last_name, phone),
                self.submit_request,
                self.check_result,
                self.update_status,
                self.complete_task
            ]
            
            for step in steps:
                if not step():
                    error_msg = self.get_error_message()
                    self.logger.error(f"步骤执行失败: {error_msg}")
                    return False
                time.sleep(random.uniform(1, 2))  # 每个步骤之间添加随机延迟
                    
            self.state.success = True
            return True
            
        except Exception as e:
            self.logger.error(f"处理解锁请求失败: {str(e)}")
            self.state.error_message = str(e)
            return False
        finally:
            self.cleanup()

    def run(self, imei: str, email: str, first_name: str, last_name: str, phone: str) -> bool:
        """
        运行解锁流程
        :param imei: IMEI号码
        :param email: 邮箱地址
        :param first_name: 名字
        :param last_name: 姓氏
        :param phone: 电话号码
        :return: 是否成功
        """
        try:
            # 初始化浏览器
            if not self.setup():
                return False
                
            # 设置用户信息
            self.state = UnlockState()
            self.state.email = email
            self.state.car_id_data = {
                'imei': imei,
                'first_name': first_name,
                'last_name': last_name,
                'phone': phone
            }
                
            # 导航到解锁页面
            if not self.navigate_page():
                self.logger.error("导航到页面失败")
                return False
                    
            # 选择无手机号选项
            if not self.select_no_phone():
                self.logger.error("选择无手机号选项失败")
                return False
                
            # 输入IMEI
            if not self.input_imei(imei):
                self.logger.error("IMEI验证失败")
                return False

            # 勾选同意协议
            if not self.confirm_checkbox():
                self.logger.error("勾选同意协议失败")
                return False
                
            # 点击下一步
            if not self.next_step():
                self.logger.error("点击下一步失败")
                return False
                
            # 填写个人信息
            if not self.input_personal_info(
                email=email,
                first_name=first_name,
                last_name=last_name,
                phone=phone
            ):
                self.logger.error("填写个人信息失败")
                return False
                
            # 提交请求
            if not self.submit_request():
                self.logger.error("提交请求失败")
                return False
                
            # 检查结果并处理邮件确认
            if not self.check_result():
                self.logger.error("检查结果失败")
                return False
                
            # 如果有请求编号但没有结果，再次查询状态
            if self.state.request_number and not self.state.result_message:
                self.logger.info("已获取请求编号，正在查询最终解锁状态...")
                # 多次尝试查询，最多10次
                if not self.query_unlock_status(self.state.request_number, imei=imei, max_attempts=10):
                    self.logger.warning("未能获取最终解锁状态，可能需要稍后再查询")
                    
                    # 在日志中记录后续查询所需的信息
                    self.logger.info(f"可以使用以下命令查询解锁状态: python main.py status --id <record_id> --request-number {self.state.request_number} --imei {imei}")
            
            # 获取解锁结果
            result = self.state.result_message
            if result:
                self.logger.info(f"解锁结果: {result}")
                success = "已解锁" in result or "Unlocked" in result or self.state.status == self.STATUS_SUCCESS
                if success:
                    self.logger.info("解锁成功！")
                    self.state.success = True
                else:
                    self.logger.warning("解锁失败，原因: " + result)
                return success
            else:
                self.logger.error("未获取到解锁结果")
                return False
            
        except Exception as e:
            self.logger.error(f"运行解锁流程失败: {str(e)}")
            self.state.error_message = str(e)
            return False
        finally:
            self.cleanup()

    def update_status(self) -> bool:
        """更新任务状态"""
        try:
            self.logger.info("正在更新任务状态...")
            if self.state.status == self.STATUS_CONFIRMED:
                self.logger.info(f"解锁请求已确认，请求编号: {self.state.request_number}")
            elif self.state.status == self.STATUS_SUCCESS:
                self.logger.info(f"解锁成功，请求编号: {self.state.request_number}")
            elif self.state.status == self.STATUS_TECH_FAILED:
                self.logger.error(f"解锁失败（技术原因）: {self.state.error_message}")
            else:
                self.logger.error(f"解锁失败: {self.state.error_message}")
            return True
            
        except Exception as e:
            self.logger.error(f"更新任务状态失败: {str(e)}")
            return False
            
    def complete_task(self) -> bool:
        """完成任务"""
        try:
            self.logger.info("正在完成任务...")
            
            # 清理资源
            self.cleanup()
            
            self.logger.info("任务完成")
            return True
            
        except Exception as e:
            self.logger.error(f"完成任务失败: {str(e)}")
            return False

    def switch_to_latest_tab(self) -> None:
        """切换到最新打开的标签页"""
        try:
            # 获取标签页数量
            tabs_count = self.browser.tabs_count
            if tabs_count > 1:
                self.logger.info(f"发现 {tabs_count} 个标签页，切换到最后一个")
                # 切换到最后一个标签页
                self.page = self.browser.get_tab(tabs_count - 1)
                # 激活标签页
                self.browser.activate_tab(tabs_count - 1)
        except Exception as e:
            self.logger.error(f"切换标签页失败: {str(e)}")

    def navigate_status_page(self) -> bool:
        """访问状态查询页面"""
        try:
            # 访问状态查询页面
            status_url = "https://www.att.com/deviceunlock/status"
            self.page.get(status_url)
            time.sleep(5)  # 等待页面加载
            
            # 处理可能出现的弹窗
            self.handle_popups()
            
            # 检查是否成功到达状态页面
            if "deviceunlock/status" in self.page.url:
                self.logger.info("成功访问状态查询页面")
                return True
            else:
                self.logger.error(f"访问状态查询页面失败，当前URL: {self.page.url}")
                return False
                
        except Exception as e:
            self.logger.error(f"访问状态查询页面失败: {str(e)}")
            return False
            
    def fill_status_form(self, request_number: str, imei: str = None) -> bool:
        """填写状态查询表单"""
        try:
            # 如果提供了IMEI，则填写IMEI
            if imei:
                imei_input = self.page.ele('css:input[name="imeino"]')
                if not imei_input:
                    self.logger.error("未找到IMEI输入框")
                    return False
                
                # 清空输入框并填写IMEI
                imei_input.clear()
                time.sleep(1)
                
                # 模拟人工输入
                ac = self.page.actions
                ac.move_to(imei_input)
                ac.click()
                time.sleep(0.5)
                
                for char in imei:
                    ac.type(char)
                    time.sleep(random.uniform(0.1, 0.2))
                
                time.sleep(1)
            
            # 填写请求编号
            request_input = self.page.ele('css:input[name="requestNumber"]')
            if not request_input:
                self.logger.error("未找到请求编号输入框")
                return False
            
            # 清空输入框并填写请求编号
            request_input.clear()
            time.sleep(1)
            
            # 模拟人工输入
            ac = self.page.actions
            ac.move_to(request_input)
            ac.click()
            time.sleep(0.5)
            
            for char in request_number:
                ac.type(char)
                time.sleep(random.uniform(0.1, 0.2))
            
            time.sleep(1)
            
            # 等待按钮可点击
            wait_time = 0
            while wait_time < 10:  # 最多等待10秒
                if not self.page.ele('css:.btn-primary[disabled]'):
                    break
                time.sleep(1)
                wait_time += 1
            
            self.logger.info("已完成状态查询表单填写")
            return True
            
        except Exception as e:
            self.logger.error(f"填写状态查询表单失败: {str(e)}")
            return False 